﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using eTerm.NetSocket.PlugIn;

namespace eTerm.NetSocket
{
    /// <summary>
    /// 插件基类
    /// </summary>
    public abstract class BasePlugIn: BaseDisposable,IPlugIn
    {
        #region IPlugIn Members

        /// <summary>
        /// 插件执行完成.
        /// </summary>
        public event EventHandler<PlugInArgs> OnExecuted;

        /// <summary>
        /// 插件执行异常.
        /// </summary>
        public event EventHandler<PlugInArgs> OnPlugInException;

        /// <summary>
        /// 插件名称.
        /// </summary>
        /// <value>The name of the plug in.</value>
        public abstract string PlugInName { get; }

        /// <summary>
        /// 插件指令.
        /// <remarks>
        /// 以!开头的插件指令
        /// </remarks>
        /// </summary>
        /// <value>The plug in CMD.</value>
        public abstract string PlugInCmd { get; }


        /// <summary>
        /// 异步执行插件
        /// </summary>
        private delegate void ExecutePlugInCallback(BaseTermSocket eTermSession, eTerm363Session TSession, string Packet);

        /// <summary>
        /// 执行指令插件.
        /// </summary>
        /// <param name="eTermSession">eTerm配置会话.</param>
        /// <param name="TSession">客户端会话.</param>
        /// <param name="Packet">用户指令包.</param>
        public void Execute(BaseTermSocket eTermSession, eTerm363Session TSession, string Packet)
        {
            try {
                if (TSession == null||(TSession.IsApiSession && !AllowAPISession) ) return;
                //ExecutePlugIn(eTermSession, TSession, Packet);
                
                ExecutePlugInCallback m_Execute = new ExecutePlugInCallback(ExecutePlugIn);
                m_Execute.BeginInvoke(eTermSession, TSession, Packet, new AsyncCallback(delegate(IAsyncResult iar) {
                    ExecutePlugInCallback m_ExecuteVar = iar.AsyncState as ExecutePlugInCallback;
                    m_ExecuteVar.EndInvoke(iar);
                    iar.AsyncWaitHandle.Close();
                    OnExecutedPlugIn();
                }), m_Execute);
                
            }
            catch (Exception ex) {
                OnOccurException(ex);   
            }
        }

        ///// <summary>
        ///// 是否将该指含串合并一次发送
        ///// </summary>
        //public bool IsMerger
        //{
        //    get;
        //    set;
        //}

        /// <summary>
        /// API用户是否允许使用该插件
        /// </summary>
        public virtual bool AllowAPISession {
            get { return false; }
        }

        /// <summary>
        /// Called when [executed].
        /// </summary>
        protected virtual void OnExecutedPlugIn()
        {
            EventHandler<PlugInArgs> handler = this.OnExecuted;
            if (handler != null)
            {
                handler(this, new PlugInArgs(this, string.Empty));
            }
        }

        /// <summary>
        /// Called when [executed].
        /// </summary>
        protected virtual void OnOccurException(Exception ex)
        {
            EventHandler<PlugInArgs> handler = this.OnExecuted;
            if (handler != null)
            {
                handler(this, new PlugInArgs(this, ex.Message));
            }
        }



        /// <summary>
        /// 插件内部逻辑，必须重写.
        /// </summary>
        /// <param name="eTermSession">The e term session.</param>
        /// <param name="TSession">The T session.</param>
        /// <param name="Packet">The packet.</param>
        protected abstract void ExecutePlugIn(BaseTermSocket eTermSession, eTerm363Session TSession, string Packet);

        /// <summary>
        /// 插件帮助信息.
        /// </summary>
        /// <value>The description.</value>
        public virtual string Description { get { return string.Format(@"
        {0}
",PlugInName); } }

        /// <summary>
        /// 是否为系统插件
        /// </summary>
        /// <value></value>
        public virtual bool IsSystem { get { return false; } }

        #endregion
    }
}
